package cn.qiyu5522.tk_ems.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.qiyu5522.tk_ems.entity.Menu;
import cn.qiyu5522.tk_ems.entity.Role;
import cn.qiyu5522.tk_ems.entity.RoleMenu;
import cn.qiyu5522.tk_ems.entity.dto.MenuDTO;
import cn.qiyu5522.tk_ems.entity.dto.QueryParamDTO;
import cn.qiyu5522.tk_ems.entity.vo.MenuVO;
import cn.qiyu5522.tk_ems.mapper.MenuMapper;
import cn.qiyu5522.tk_ems.mapper.RoleMapper;
import cn.qiyu5522.tk_ems.mapper.RoleMenuMapper;
import cn.qiyu5522.tk_ems.result.CustomMapResult;
import cn.qiyu5522.tk_ems.result.R;
import cn.qiyu5522.tk_ems.service.MenuService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Tonkey
 * @since 2023-02-27
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private RoleMenuMapper roleMenuMapper;
    @Resource
    private RoleMapper roleMapper;

    @Override
    public R queryMenuListByCondition(QueryParamDTO<MenuDTO> queryParamDTO) {
        MenuDTO condition = queryParamDTO.getCondition();
        IPage<Menu> page = new Page<>(queryParamDTO.getCurrentPage(),queryParamDTO.getPageSize());
        LambdaQueryWrapper<Menu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(condition.getTitle()),Menu::getTitle, condition.getTitle());
        baseMapper.selectPage(page,lambdaQueryWrapper);
        Map<String, Object> map = CustomMapResult
                .packagingResult(page.getRecords(), queryParamDTO.getCurrentPage(), queryParamDTO.getPageSize(), page.getTotal());
        return R.ok().data("menuIPage",map);
    }

    @Override
    public R getMenuTree() {
        List<Menu> menuList1 = baseMapper.selectList(null);
        // 实体类转VO
        List<MenuVO> menuList = objectMapper.convertValue(menuList1, new TypeReference<List<MenuVO>>() {
        });
        // 构建菜单树
        List<MenuVO> menuTree = new ArrayList<>();
        for (MenuVO menu : menuList) {
            if (menu.getParentId() == null) {
                // 该菜单为根节点
                menu.setChildren(getChildren(menu.getId(), menuList));
                menuTree.add(menu);
            }
        }
        return R.ok().data("menuTree",menuTree);
    }

    private List<MenuVO> getChildren(Integer parentId, List<MenuVO> menuList) {
        // 获取子菜单
        List<MenuVO> children = new ArrayList<>();
        for (MenuVO menu : menuList) {
            if (parentId.equals(menu.getParentId())) {
                // 递归获取子菜单
                menu.setChildren(getChildren(menu.getId(), menuList));
                children.add(menu);
            }
        }
        return children;
    }


    @Override
    public R saveMore(List<MenuDTO> menuDTOs) {
        // DTO转实体类
        List<Menu> menus = objectMapper.convertValue(menuDTOs, new TypeReference<List<Menu>>() {
        });
        Integer integer = baseMapper.insertBatchSomeColumn(menus);
        return integer>0 ? R.ok().message("添加成功"):R.error().message("添加失败");
    }

    @Override
    public R queryMenuListByRole() {
        // 获取登录用户拥有的角色
        List<String> roleList = StpUtil.getRoleList();
        if(CollectionUtil.isEmpty(roleList)){
            return R.ok().data("menuTree",new ArrayList<MenuVO>(0));
        }
        // 根据角色名称查询角色表，获取角色编号
        LambdaQueryWrapper<Role> roleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleLambdaQueryWrapper.in(Role::getName,roleList);
        List<Role> roles = roleMapper.selectList(roleLambdaQueryWrapper);
        List<Integer> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());
        // 根据角色编号查询 角色菜单关联表 获取菜单编号
        LambdaQueryWrapper<RoleMenu> roleMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleMenuLambdaQueryWrapper.in(RoleMenu::getRoleId,roleIds);
        List<RoleMenu> roleMenus = roleMenuMapper.selectList(roleMenuLambdaQueryWrapper);
        if(CollectionUtil.isEmpty(roleMenus)){
            return R.ok().data("menuTree",new ArrayList<MenuVO>(0));
        }
        // 拿到菜单编号
        List<Integer> menuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
        // 查询菜单表，获取对应菜单信息
        List<Menu> menus = baseMapper.selectBatchIds(menuIds);
        // 根据菜单编号去重
        List<Menu> menuList = menus.stream().distinct().collect(Collectors.toList());

        // 实体类转VO
        List<MenuVO> menuVOS = objectMapper.convertValue(menuList, new TypeReference<List<MenuVO>>() {
        });

        // 构建菜单树
        List<MenuVO> menuTree = new ArrayList<>();
        for (MenuVO menu : menuVOS) {
            if (menu.getParentId() == null) {
                // 该菜单为根节点
                menu.setChildren(getChildren(menu.getId(), menuVOS));
                menuTree.add(menu);
            }
        }
        return R.ok().data("menuTree",menuTree);
    }

    @Override
    public Integer queryChildrenMenuMaxId(Integer pid) {
        if(pid.equals(0)){
            // 查询最后一个根级菜单的编号,并 将编号加1000返回
            Integer maxId = baseMapper.queryLastParentMenuId();
            return maxId;
        }
        LambdaQueryWrapper<Menu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Menu::getParentId,pid);
        List<Menu> menus = baseMapper.selectList(lambdaQueryWrapper);
        // 空说明，本次添加操作为该菜单的第一个子菜单
        if(ObjectUtil.isEmpty(menus)){
            lambdaQueryWrapper.clear();
            lambdaQueryWrapper.eq(Menu::getId,pid);
            Menu menu = baseMapper.selectOne(lambdaQueryWrapper);
            // 该菜单为子菜单
            if(ObjectUtil.isNotEmpty(menu.getParentId())){
                return pid*100+1;
            }else{
                // 根据菜单
                // 上级菜单编号+1
                return pid+1;
            }
        }
        // 获取最大id
        Integer integer = menus.stream().map(Menu::getId).max((o1, o2) -> o1 - o2).get();
        Integer maxId = integer+1;
        return maxId;
    }

    @Override
    public R checkMenuIdIsExisting(Integer menuId) {
        Menu menu = baseMapper.selectById(menuId);
        return ObjectUtil.isNotEmpty(menu)?
                R.ok().data("flag",true).message("当前编号已存在，请换一个（例如")
                :R.ok().data("flag",false).message("允许使用");
    }

    @Override
    public R checkIsRepeatForMenuTitle(String title) {
        LambdaQueryWrapper<Menu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Menu::getTitle,title);
        Menu menu = baseMapper.selectOne(lambdaQueryWrapper);
        return ObjectUtil.isNotEmpty(menu)?
                R.ok().data("flag",true).message("菜单名称已存在，请换一个")
                :R.ok().data("flag",false).message("允许使用");
    }
}
